home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Pascal / Libraries / SpinningCursorLib / Source / SpinningCursor.c next >
Encoding:
C/C++ Source or Header  |  1993-02-05  |  4.7 KB  |  187 lines  |  [TEXT/KAHL]

  1. /*
  2. Spinning Cursor Library
  3. Distributed by Philippe Casgrain
  4.  
  5.   What you need to know:
  6.  
  7.   1) This library was taken directly and blatantly from the book "Macintosh
  8. Programming Secrets, Second Edition" (Addison-Wesley), and is distributed with
  9. the author's permission.  You should get the book, because a) it's very
  10. informative and b) there are _lots_ of source code comments which I obviously
  11. didn't type in.
  12.  
  13.   2) The library doesn't work by itself; you need to provide a resource file
  14. with two resources:
  15.   - a 'CURS' resource, which is a list of all the cursor "frames" that you want
  16. to use in your animation.  Note that if you want an animation that comes and
  17. goes (like the hand in the Apple Installer that first extends the fingers and
  18. then folds them back), you need to specify all the frames in order: the
  19. animation process goes one-way only.
  20.   - an 'acur' resource, which specifies what are the "frames" ID numbers and the
  21. order you want them in.
  22.   See the sample resource for an example.
  23.  
  24.   3) There are three procedures you want to install in your program:
  25.   - InitCursorCtl (acurResourceID: Integer);
  26. Use this routine once to initialize the cursor-animating task.  The argument is
  27. the resource ID of the 'acur' resource, _not_ the 'CURS' resources: those are
  28. contained in the 'acur' resource.
  29.  
  30.   -StartAsyncSpinning (period: Integer);
  31. This starts the spinning cursor asynchronously (i.e. you can do other tasks
  32. while the cursor spins; it should not be affected).  The argument is the delay
  33. (in ticks, or 1/60ths of second) between each cursor "frame".  For instance, if
  34. you want to change the cursor each .25 second, set this value to 10.
  35.  
  36.   - StopAsyncSpinning;
  37. This stops the spinning cursor.
  38.  
  39.   4) None of these tasks save the current cursor.  You should do that yourself,
  40. and restore it afterwards.
  41.  
  42.  
  43.   Other than that, share it and enjoy it!
  44.  
  45.   If you do use that library in anything that goes further than your desk, I
  46. would appreciate you telling me (I don't want a mention in your program, 'cause
  47. I only typed that code in!).  Hey! a postcard would be real nice!  But e-mail is
  48. fine (though I can't stick e-mail on my fridge and show it to my kids).
  49.  
  50.   Thanks to you all, out there on the 'net, and special thanks to Keith Rollin
  51. (and Scott Knaster) for de-mystifying Macintosh programming.
  52.  
  53. Philippe Casgrain
  54. casgrain@ere.umontreal.ca
  55.  
  56. 4 980 Boulevard Lalande
  57. Pierrefonds, Quebec
  58. Canada      H8Y 1V8
  59.  
  60. */
  61.  
  62. #include "SpinningCursor.h"
  63. #include "Retrace.h"
  64.  
  65. typedef struct {
  66.     unsigned   short numCursors;
  67.     unsigned   short index;
  68.     CursHandle cursors[1];
  69. } Acur, *AcurPtr, **AcurHandle;
  70.  
  71. typedef struct {
  72.     VBLTask theTask;
  73.     long    A5;
  74. } VBLTaskWithA5, *VBLTaskWithA5Ptr;
  75.  
  76. AcurHandle       pCursors;
  77. VBLTaskWithA5Ptr pCursorTask;
  78. short            pDesiredCount;
  79.  
  80. char CrsrBusy : 0x08CD;
  81.  
  82. void InitCursorCtl(short resID)
  83. {
  84.     short       cursorCount;
  85.     CursHandle* workPtr;
  86.  
  87.     pCursors = (AcurHandle) GetResource('acur',resID);
  88.     
  89.     cursorCount = (**pCursors).numCursors;
  90.     (**pCursors).numCursors *= 32;
  91.     (**pCursors).index = 0;
  92.     
  93.     HLock((Handle) pCursors);
  94.     workPtr = (**pCursors).cursors;
  95.     
  96.     while (cursorCount--) {
  97.         *workPtr++ = (CursHandle) GetResource('CURS', *(short*) workPtr);
  98.     }
  99.     HUnlock((Handle) pCursors);
  100. }
  101.  
  102. void SpinCursor(short increment)
  103. {
  104.     short oldIndex;
  105.     short newIndex;
  106.     
  107.     oldIndex = (**pCursors).index / 32;
  108.     
  109.     (**pCursors).index += increment;
  110.     (**pCursors).index %= (**pCursors).numCursors;
  111.     
  112.     newIndex = (**pCursors).index / 32;
  113.     
  114.     if (newIndex != oldIndex) {
  115.         SetCursor(*(**pCursors).cursors[newIndex]);
  116.     }
  117. }
  118.  
  119. void LockCursorData(void)
  120. {
  121.     short       cursorCount;
  122.     CursHandle* workPtr;
  123.     
  124.     cursorCount = (**pCursors).numCursors / 32;
  125.     
  126.     HLockHi((Handle) pCursors);
  127.     workPtr = (**pCursors).cursors;
  128.     while (cursorCount--) {
  129.         HLockHi((Handle) *workPtr++);
  130.     }
  131. }
  132.  
  133. void UnlockCursorData(void)
  134. {
  135.     short       cursorCount;
  136.     CursHandle* workPtr;
  137.     
  138.     cursorCount = (**pCursors).numCursors / 32;
  139.     
  140.     workPtr = (**pCursors).cursors;
  141.     while (cursorCount--) {
  142.         HUnlock((Handle) *workPtr++);
  143.     }
  144.     HUnlock((Handle) pCursors);
  145. }
  146.  
  147.  
  148. void StartAsyncSpinning(short period)
  149. {
  150.     LockCursorData();
  151.     
  152.     pDesiredCount = period;
  153.     
  154.     pCursorTask = (VBLTaskWithA5Ptr) NewPtr(sizeof(VBLTaskWithA5));
  155.     pCursorTask->theTask.qType = vType;
  156.     pCursorTask->theTask.vblAddr = (ProcPtr) MySpinner;
  157.     pCursorTask->theTask.vblCount = pDesiredCount;
  158.     pCursorTask->theTask.vblPhase = 0;
  159.     pCursorTask->A5 = (long) CurrentA5;
  160.     
  161.     (void) VInstall((QElemPtr) pCursorTask);
  162. }
  163.  
  164. void StopAsyncSpinning(void)
  165. {
  166.     (void) VRemove((QElemPtr) pCursorTask);
  167.     DisposePtr((Ptr) pCursorTask);
  168.     UnlockCursorData();
  169. }
  170.  
  171. void MySpinner(void)
  172. {
  173.     long             oldA5;
  174.     VBLTaskWithA5Ptr myTaskPtr;
  175.     
  176.     asm {
  177.         move.l A0, myTaskPtr
  178.     }
  179.     
  180.     if (CrsrBusy == 0) {
  181.         oldA5 = SetA5(myTaskPtr->A5);
  182.         SpinCursor(32);
  183.         myTaskPtr->theTask.vblCount = pDesiredCount;
  184.         (void) SetA5(oldA5);
  185.     }
  186. }
  187.